#ifndef __OC_Prerequisites_H__
#define __OC_Prerequisites_H__

#if defined(_MSC_VER)
#ifndef OCMain_EXPORTS
#define _MainExport  __declspec(dllimport)
#else
#define _MainExport  __declspec(dllexport)
#endif
#else
#define _MainExport
#endif

#include "StdHeaders.h"

#define Singleton(name) name::getSingleton()
#define SingletonPtr(name) name::getSingletonPtr()

#define CORE_NEW new
#define CORE_DELETE delete
#define CORE_SAFE_DELETE(p) { if(p){delete(p);  (p)=NULL;} }
#define CORE_SAFE_DELETE_ARRAY(p) { if(p){delete[] (p);  (p)=NULL;} }
#define CORE_SAFE_RELEASE(p) { if(p){ (p)->Release();  (p)=NULL;} }
#define CORE_FRIEND_CLASS(name) friend class name

#define CORE_AUTO_MUTEX_NAME mutex
#define CORE_AUTO_MUTEX std::mutex CORE_AUTO_MUTEX_NAME
#define CORE_LOCK_AUTO_MUTEX std::unique_lock<std::mutex> coreAutoMutexLock(CORE_AUTO_MUTEX_NAME)

// Read-write mutex
#define CORE_RW_MUTEX(name) std::shared_mutex name
#define CORE_LOCK_RW_MUTEX_READ(name) std::shared_lock<std::shared_mutex> corenameLock(name)
#define CORE_LOCK_RW_MUTEX_WRITE(name) std::unique_lock<std::shared_mutex> corenameLock(name)

#define CORE_MUTEX(name) std::mutex name
#define CORE_LOCK_MUTEX(name) std::unique_lock<std::mutex> exclusive(name)
#define CORE_LOCK_MUTEX_NAMED(mutexName, lockName) std::unique_lock<std::mutex> lockName(mutexName)


#define CORE_RECURSIVE_MUTEX(name) std::recursive_mutex name
#define CORE_RECURSIVE_LOCK_MUTEX(name) std::unique_lock<std::recursive_mutex> exclusive(name)
#define CORE_RECURSIVE_LOCK_MUTEX_NAMED(mutexName, lockName) std::unique_lock<std::recursive_mutex> lockName(mutexName)

//#define CORE_THREAD_SYNCHRONISER(sync) std::condition_variable sync;
#define CORE_THREAD_SYNCHRONISER(sync) std::condition_variable_any sync
#define CORE_THREAD_WAIT(sync, mutex) sync.wait(mutex)
#define CORE_THREAD_NOTIFY_ONE(sync) sync.notify_one()
#define CORE_THREAD_NOTIFY_ALL(sync) sync.notify_all()

typedef unsigned int uint32;
typedef unsigned short uint16;
typedef unsigned char uint8;
typedef int int32;
typedef short int16;
typedef char int8;

#if _WIN32
	typedef unsigned __int64 uint64;
	typedef __int64 int64;
#else
	typedef unsigned long long uint64;
	typedef long long int64;
#endif

namespace OCPP
{
	typedef unsigned char uchar;
	typedef unsigned short ushort;
	typedef unsigned int uint;
	typedef unsigned long ulong;

	typedef std::string String;
	typedef std::wstring WString;
	typedef std::stringstream StringStream;
	typedef std::vector<String> StringVector;
	typedef std::vector<float> FloatVector;
	typedef std::vector<double> DoubleVector;
	typedef std::vector<uint8> Uint8Vector;
	typedef std::vector<int16> Int16Vector;
	typedef std::vector<uint16> Uint16Vector;
	typedef std::vector<uint32> Uint32Vector;
	typedef std::vector<int32> IntVector;
	typedef std::vector<long> LongVector;
	typedef std::map<String, String> StringMap;

	class CHttpClient;
	class WorkQueue;
	class WorkQueueThread;
	class DynLib;
	class ApplicationUsage;
	typedef unsigned long long int RequestID;

	class AxisAlignedBox;
	class Affine3;
	class Radian;
	class Degree;
	template <int dims, typename T> class Vector;
	typedef Vector<2, float> Vector2;
	typedef Vector<2, int> Vector2i;
	typedef Vector<3, float> Vector3;
	typedef Vector<3, float> Vector3f;
	typedef Vector<3, int> Vector3i;
	typedef Vector<4, float> Vector4;
	typedef Vector<4, float> Vector4f;
	typedef Vector<4, int> Vector4i;
	class Matrix3;
	class Matrix4;
	class Ray;
	class Plane;
	class Sphere;
	class Quaternion;
	typedef std::vector<Vector2> Vector2List;
	typedef std::vector<Vector3> Vector3List;
	typedef std::vector<Vector4> Vector4List;
	typedef std::vector<Vector2i> Vector2iList;
	typedef std::vector<Vector3i> Vector3iList;
	typedef std::vector<Vector4i> Vector4iList;
	class DataStream;
	class MemoryDataStream;
	typedef std::shared_ptr<DataStream> DataStreamPtr;
	typedef std::shared_ptr<MemoryDataStream> MemoryDataStreamPtr;

#if WIN32
#define OGRE_IGNORE_DEPRECATED_BEGIN __pragma(warning(push)) \
    __pragma(warning(disable:4996))
#define OGRE_IGNORE_DEPRECATED_END __pragma(warning(pop))
#else
#define OGRE_IGNORE_DEPRECATED_BEGIN _Pragma("GCC diagnostic push") \
    _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
#define OGRE_IGNORE_DEPRECATED_END _Pragma("GCC diagnostic pop")
#endif

#define OGRE_ENDIAN_LITTLE 1
#define OGRE_ENDIAN_BIG 2

	//#define OGRE_CONFIG_BIG_ENDIAN

#if defined(OGRE_CONFIG_BIG_ENDIAN) || (defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
#    define OGRE_ENDIAN OGRE_ENDIAN_BIG
#else
#    define OGRE_ENDIAN OGRE_ENDIAN_LITTLE
#endif
}

namespace CppTime {
	class Timer;
}

namespace sqlite3pp
{
	class database;
}

#define SI_SUPPORT_IOSTREAMS

#endif
